{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Simple Reinforcement Learning with Tensorflow: Part 0 - Q-Tables\n",
    "In this iPython notebook we implement a Q-Table algorithm that solves the FrozenLake problem. To learn more, read here: https://medium.com/@awjuliani/simple-reinforcement-learning-with-tensorflow-part-0-q-learning-with-tables-and-neural-networks-d195264329d0\n",
    "\n",
    "For more reinforcment learning tutorials, see:\n",
    "https://github.com/awjuliani/DeepRL-Agents"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import gym\n",
    "import numpy as np\n",
    "import random\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load the environment"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[2017-03-08 19:31:58,969] Making new env: FrozenLake-v0\n"
     ]
    }
   ],
   "source": [
    "env = gym.make('FrozenLake-v0')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Implement Q-Table learning algorithm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "#Initialize table with all zeros\n",
    "Q = np.zeros([env.observation_space.n,env.action_space.n])\n",
    "# Set learning parameters\n",
    "lr = .8\n",
    "y = .95\n",
    "num_episodes = 2000\n",
    "#create lists to contain total rewards and steps per episode\n",
    "#jList = []\n",
    "rList = []\n",
    "for i in range(num_episodes):\n",
    "    #Reset environment and get first new observation\n",
    "    s = env.reset()\n",
    "    rAll = 0\n",
    "    d = False\n",
    "    j = 0\n",
    "    #The Q-Table learning algorithm\n",
    "    while j < 99:\n",
    "        j+=1\n",
    "        #Choose an action by greedily (with noise) picking from Q table\n",
    "        a = np.argmax(Q[s,:] + np.random.randn(1,env.action_space.n)*(1./(i+1)))\n",
    "        #Get new state and reward from environment\n",
    "        s1,r,d,_ = env.step(a)\n",
    "        #Update Q-Table with new knowledge\n",
    "        Q[s,a] = Q[s,a] + lr*(r + y*np.max(Q[s1,:]) - Q[s,a])\n",
    "        rAll += r\n",
    "        s = s1\n",
    "        if d == True:\n",
    "            break\n",
    "    #jList.append(j)\n",
    "    rList.append(rAll)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Score over time: 0.5345\n"
     ]
    }
   ],
   "source": [
    "print(\"Score over time: \" +  str(sum(rList)/num_episodes))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Final Q-Table Values\n",
      "[[  5.65665336e-01   1.32702822e-02   1.84476143e-04   2.78297656e-02]\n",
      " [  1.11953138e-03   1.33937995e-04   0.00000000e+00   5.89997642e-01]\n",
      " [  2.73597828e-02   0.00000000e+00   5.28510052e-03   5.24379779e-01]\n",
      " [  0.00000000e+00   0.00000000e+00   0.00000000e+00   4.26526621e-01]\n",
      " [  6.53693362e-01   1.68814092e-03   2.63829516e-03   1.91123462e-03]\n",
      " [  0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00]\n",
      " [  8.09674056e-02   4.48724195e-05   2.20163475e-09   2.58590894e-06]\n",
      " [  0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00]\n",
      " [  0.00000000e+00   0.00000000e+00   3.07917957e-03   5.60094060e-01]\n",
      " [  3.31391432e-04   4.99781611e-01   0.00000000e+00   0.00000000e+00]\n",
      " [  8.47572076e-01   3.13583798e-04   8.98214216e-04   2.51734273e-04]\n",
      " [  0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00]\n",
      " [  0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00]\n",
      " [  1.32122644e-05   5.31944387e-05   8.97199769e-01   4.44037973e-04]\n",
      " [  0.00000000e+00   0.00000000e+00   9.96736292e-01   0.00000000e+00]\n",
      " [  0.00000000e+00   0.00000000e+00   0.00000000e+00   0.00000000e+00]]\n"
     ]
    }
   ],
   "source": [
    "print(\"Final Q-Table Values\")\n",
    "print(Q)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [conda env:keras]",
   "language": "python",
   "name": "conda-env-keras-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
